/**
 * Created by macos on 14/11/11.
 */

var net = require('net'),
  EventEmitter = require('events').EventEmitter,
  util = require('util');

var async = require('async'),
  _ = require('lodash');

var checksum = require('./checksum'),
  secret = require('./secret');

(function() {

  var root = this;

  /**
   * 向TCP服务器写入数据，并且获得反馈。
   * @param hex 字符串形式的16进制数据
   * @param callback
   */
  function writeHex(hex, callback) {
    callback = callback || function() {};

    var client = this._client;

    client.write(hex, 'hex', function() {

      client.once('data', function(data) {
        callback(data);
      });

    });
  };

  /**
   * 登录第一步，发送UUID
   * @param next
   */
  function login1(next) {
    var cmd = "faaf";
    var type = "00";
    var uuid = this.loginInfo.uuid;
    var hex = cmd + type + uuid;

    var buf = new Buffer(hex, 'hex');
    var chksum = checksum.checksum(buf, 0, buf.length);

    hex = hex + chksum;
    writeHex = _.bind(writeHex, {_client:this._client});
    writeHex(hex, function(data){
      var cmd = data.slice(0,2).toString('hex');
      var type = data.slice(2, 3).toString('hex');
      if (cmd == 'affa' &&  type == '01') {
        return next(null, data);
      } else {
        return next(uuid + ' is error');
      }
    })

  }

  /**
   * 登录第二步
   * @param next
   */
  function login2(data, next) {

    var checksumStr = checksum.checksum(data);
    if (!checksum.validate(data, checksumStr)) {
      return next('checksum is error')
    }

    var cmd = "faaf";
    var type = "01";
    var pubKey = data.slice(3, 5);
    var uuidBuffer = new Buffer(this.loginInfo.uuid, 'hex');
    var secretKey = secret.secretKey(uuidBuffer, pubKey);

    var hex = cmd + type + secretKey;
    var buf = new Buffer(hex, 'hex');
    var chksum = checksum.checksum(buf, 0, buf.length);

    hex = hex + chksum;
    writeHex = _.bind(writeHex, {_client:this._client});
    writeHex(hex, function(data){

      var status = data.slice(3, 4).toString('hex');
      if (status === '01') {
        next(null, true);
      } else {
        next(null, false)
      }

    });

  }

  /**
   * 将低位的16进制字节转化成数字
   * @param buffer
   * @returns {number}
   */
  function lowHex2Number(buffer) {
    var hex = buffer.toString('hex');
    var number = parseInt(hex, '16');
    console.log(number)
    return number;
  }

  /***
   * 将数字转换成高位的字符串形式的16进制字节
   * @param number
   * @returns {*}
   */
  function number2HighHex(number) {
    var hex = number.toString(16);
    if (hex.length == 1) hex = '0' + hex;

    if (hex.length < 8) {
      var fillLen = 8 - hex.length;
      for (var i = 0; i < fillLen; i++) {
        hex = hex + '0';
      }
    }

    return hex;
  }

  function sessionId() {

    var sid = ""
    for (var i = 0; i < 6; i++) {
      var num = _.random(255);

      if (num < 15) {
        sid += '0' + num.toString(16);
      } else {
        sid += num.toString(16);
      }
    }

    return sid;
  }

  function TcpClient() {
    EventEmitter.call(this);

    this.connected = false;
    this._client = null;
  }
  util.inherits(TcpClient, EventEmitter);

  TcpClient.prototype.connect = function(option, callback) {
    callback = callback || function() {};
    this._client = net.connect(option);

    this._client.on('connect', function() {
      this.connected = true;
      callback();
    });

    this._client.once('error', function(err) {
      this.emit('error', err);
    });

    this._client.once('end', function() {
      this.connected = false;
      this.emit('end');
    })//
  }

  /**
   * 登录TCP服务器
   * @param config
   * @param callback
   */
  TcpClient.prototype.login = function(loginInfo, callback) {
    callback = callback || function() {};

    login1 = _.bind(login1, {loginInfo:loginInfo, _client:this._client} );
    login2 = _.bind(login2, {loginInfo:loginInfo, _client:this._client} );

      async.waterfall([
        login1,
        login2
      ], function(error, result) {

        if (error) {
          callback(error);
        } else {
          callback(null, result);
        }
      });

  }

  /**
   * 发送心跳
   * @param callback
   */
  TcpClient.prototype.heart = function(callback) {
    callback = callback || function() {};

    writeHex = _.bind(writeHex, {_client:this._client});
    writeHex('5aa5', function(result) {
      if (result.toString('hex') === 'a55a') {
        callback(result);
      }
    });
  }

  /**
   * 发送数据
   * @param hex 字符串形式的16进制数据
   * @param callback
   */
  TcpClient.prototype.sendData = function(hex, callback) {
    callback = callback || function() {};

    var sid = sessionId();
    hex = 'daad00' + sid + number2HighHex(hex.length / 2) + hex;
    var buf = new Buffer(hex, 'hex');
    var chksum = checksum.checksum(buf, 0, buf.length);
    hex = hex + chksum;

    writeHex = _.bind(writeHex, {_client:this._client});
    writeHex(hex, function(result) {
      
      var cmd = result.slice(0, 2).toString('hex');
      var type = result.slice(2, 3).toString('hex');
      var receSid = result.slice(3, 9).toString('hex');
      var status = result.slice(9, 10).toString('hex');

      if (cmd === 'adda' && type === '01' && sid === receSid) {
        if (status === '01') {
          status = true;
        } else {
          status = false;
        }
        callback(null, status);
      }
    });
  }


  TcpClient.prototype.onReceived = function(callback) {
    callback = callback || function() {};

    var client = this._client;

    client.on('data', function(result) {
      console.log("data:", result);

      var cmd = result.slice(0, 2).toString('hex');
      var type = result.slice(2, 3).toString('hex');

      if (cmd === 'adda' && type === '00') {

        var sid = result.slice(3, 9).toString('hex');
        var len = result.slice(9, 13).toString('hex');
        len = lowHex2Number(len);
        var content = result.slice(13, 13 + len);

        var status = callback(content);
        if (status) {
          status = '01';
        } else {
          status = '00';
        }

        //包头(2位)+类型(1位)+会话ID(6位)+状态+CHK(1位)
        var hex = 'daad01' + sid + status;
        var buf = new Buffer(hex, 'hex');
        var chksum = checksum.checksum(buf, 0, buf.length);
        hex = hex + chksum;

        client.write(hex, 'hex');
      }

    });
  }


  module.exports = TcpClient;

}());